package com.mazaiting.auth.security.extension.wechat;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import com.alibaba.fastjson.JSON;
import com.mazaiting.auth.enums.AuthenticationIdentityEnum;
import com.mazaiting.auth.enums.RefreshTypeEnum;
import com.mazaiting.auth.security.core.userdetails.member.MemberUserDetails;
import com.mazaiting.auth.security.core.userdetails.member.MemberUserDetailsServiceImpl;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;

import java.util.Objects;

/**
 * 微信认证提供者
 */
@Slf4j
@Data
public class WechatAuthenticationProvider implements AuthenticationProvider {

    private UserDetailsService userDetailsService;
    private WxMaService wxMaService;

    /**
     * 微信认证
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        try {
            WechatAuthenticationToken authenticationToken = (WechatAuthenticationToken) authentication;
            // js_code
            String code = (String) authenticationToken.getPrincipal();
            // 获取 session 信息
            WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
            // 获取 openId
            String openid = sessionInfo.getOpenid();
            // 加载用户信息
            MemberUserDetails userDetails = ((MemberUserDetailsServiceImpl) userDetailsService).loadUserByOpenId(openid);
            // 此处需要添加用户不存在的情况, 是否自动创建
            if (Objects.isNull(userDetails)) {
                // 微信用户不存在，注册成为新会员
                String sessionKey = sessionInfo.getSessionKey();
                String encryptedData = authenticationToken.getEncryptedData();
                String iv = authenticationToken.getIv();
                // 解密 encryptedData 获取用户信息
                WxMaUserInfo wxMaUserInfo = wxMaService.getUserService().getUserInfo(sessionKey, encryptedData, iv);

                // 添加会员
                log.info("微信用户信息: {}", JSON.toJSONString(wxMaUserInfo));

                userDetails = new MemberUserDetails();
            }
            // 认证身份标识:mobile
            userDetails.setAuthenticationIdentity(AuthenticationIdentityEnum.OPENID.getValue());
            // 设置刷新类型
            userDetails.setRefreshType(RefreshTypeEnum.CLIENT_WECHAT.name());
            // 需要设置权限 userDetails.getAuthorities()
            WechatAuthenticationToken result = new WechatAuthenticationToken(userDetails, userDetails.getAuthorities());
            result.setDetails(authentication.getDetails());
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    @Override
    public boolean supports(Class<?> authentication) {
        return WechatAuthenticationToken.class.isAssignableFrom(authentication);
    }
}
